import {
  Topic,
  type TopicCreationAttributes,
  type TopicDomain,
  type Difficulty,
  type ReviewStatus,
} from "../models/Topic";
import User from "../models/User";
import { Op } from "sequelize";

export interface TopicQueryParams {
  domain?: TopicDomain;
  difficulty?: Difficulty;
  reviewStatus?: ReviewStatus;
  submitterId?: number;
  page?: number;
  limit?: number;
  search?: string;
}

export interface TopicWithUser extends Topic {
  submitter?: {
    id: number;
    username: string;
    email: string;
  };
}

/**
 * 创建新题目
 */
export const createTopic = async (
  topicData: TopicCreationAttributes
): Promise<Topic> => {
  try {
    const topic = await Topic.create(topicData);
    return topic;
  } catch (error) {
    throw new Error(`创建题目失败: ${error}`);
  }
};

/**
 * 根据ID获取题目详情
 */
export const getTopicById = async (
  id: number
): Promise<TopicWithUser | null> => {
  try {
    const topic = await Topic.findByPk(id, {
      include: [
        {
          model: User,
          as: "submitter",
          attributes: ["id", "username", "email"],
        },
      ],
    });
    return topic as TopicWithUser | null;
  } catch (error) {
    throw new Error(`获取题目详情失败: ${error}`);
  }
};

/**
 * 获取题目列表
 */
export const getTopics = async (
  params: TopicQueryParams = {}
): Promise<{
  topics: TopicWithUser[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}> => {
  try {
    const {
      domain,
      difficulty,
      reviewStatus,
      submitterId,
      page = 1,
      limit = 10,
      search,
    } = params;

    const offset = (page - 1) * limit;
    const where: any = {};

    // 构建查询条件
    if (domain) where.domain = domain;
    if (difficulty) where.difficulty = difficulty;
    if (reviewStatus) where.reviewStatus = reviewStatus;
    if (submitterId) where.submitterId = submitterId;
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        // { description: { [Op.like]: `%${search}%` } }
      ];
    }

    const { count, rows } = await Topic.findAndCountAll({
      where,
      include: [
        {
          model: User,
          as: "submitter",
          attributes: ["id", "username", "email"],
        },
      ],
      order: [["createdAt", "DESC"]],
      limit: limit === -1 ? undefined : limit,
      offset,
    });

    return {
      topics: rows as TopicWithUser[],
      total: count,
      page,
      limit,
      totalPages: Math.ceil(count / limit),
    };
  } catch (error) {
    throw new Error(`获取题目列表失败: ${error}`);
  }
};

/**
 * 更新题目
 */
export const updateTopic = async (
  id: number,
  updateData: Partial<TopicCreationAttributes>
): Promise<Topic | null> => {
  try {
    const [affectedCount] = await Topic.update(
      {
        ...updateData,
        reviewStatus: "pending" as ReviewStatus,
        updatedAt: new Date(),
      },
      {
        where: { id },
      }
    );

    if (affectedCount === 0) {
      return null;
    }

    return await Topic.findByPk(id);
  } catch (error) {
    throw new Error(`更新题目失败: ${error}`);
  }
};

/**
 * 删除题目
 */
export const deleteTopic = async (id: number): Promise<boolean> => {
  try {
    const affectedCount = await Topic.destroy({
      where: { id },
    });
    return affectedCount > 0;
  } catch (error) {
    throw new Error(`删除题目失败: ${error}`);
  }
};

/**
 * 审核题目
 */
export const reviewTopic = async (
  id: number,
  reviewStatus: ReviewStatus,
  reviewReason?: string
): Promise<Topic | null> => {
  try {
    const updateData: any = { reviewStatus };
    if (reviewReason) {
      updateData.reviewReason = reviewReason;
    }

    const [affectedCount] = await Topic.update(updateData, {
      where: { id },
    });

    if (affectedCount === 0) {
      return null;
    }

    return await Topic.findByPk(id);
  } catch (error) {
    throw new Error(`审核题目失败: ${error}`);
  }
};

/**
 * 增加收藏数量
 */
export const incrementStarCount = async (id: number): Promise<Topic | null> => {
  try {
    const topic = await Topic.findByPk(id);
    if (!topic) {
      return null;
    }

    await topic.increment("starCount");
    return await Topic.findByPk(id);
  } catch (error) {
    throw new Error(`增加收藏数量失败: ${error}`);
  }
};

/**
 * 减少收藏数量
 */
export const decrementStarCount = async (id: number): Promise<Topic | null> => {
  try {
    const topic = await Topic.findByPk(id);
    if (!topic) {
      return null;
    }

    if (topic.starCount > 0) {
      await topic.decrement("starCount");
    }
    return await Topic.findByPk(id);
  } catch (error) {
    throw new Error(`减少收藏数量失败: ${error}`);
  }
};

/**
 * 获取领域统计
 */
export const getDomainStats = async (
  params: TopicQueryParams = {}
): Promise<Array<{ domain: TopicDomain; count: number }>> => {
  try {
    const { difficulty, reviewStatus, submitterId, search } = params;

    // 构建筛选条件，但不包括domain筛选
    // 因为我们要统计所有domain的数量
    const where: any = {};
    if (difficulty) where.difficulty = difficulty;
    if (reviewStatus) where.reviewStatus = reviewStatus;
    if (submitterId) where.submitterId = submitterId;
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        // { description: { [Op.like]: `%${search}%` } }
      ];
    }

    // 先根据筛选条件筛选，再按领域统计数量
    const stats = await Topic.findAll({
      where: where, // 先筛选（不包括domain）
      attributes: [
        "domain",
        [Topic.sequelize!.fn("COUNT", Topic.sequelize!.col("id")), "count"],
      ],
      group: ["domain"], // 再分组统计
      raw: true,
    });

    return stats.map((stat) => ({
      domain: stat.domain as TopicDomain,
      count: parseInt(stat.count as string),
    }));
  } catch (error) {
    throw new Error(`获取领域统计失败: ${error}`);
  }
};

/**
 * 获取难度统计
 */
export const getDifficultyStats = async (
  params: TopicQueryParams = {}
): Promise<Array<{ difficulty: Difficulty; count: number }>> => {
  try {
    const { domain, reviewStatus, submitterId, search } = params;

    // 构建筛选条件，但不包括difficulty筛选
    // 因为我们要统计所有difficulty的数量
    const where: any = {};
    if (domain) where.domain = domain;
    if (reviewStatus) where.reviewStatus = reviewStatus;
    if (submitterId) where.submitterId = submitterId;
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        // { description: { [Op.like]: `%${search}%` } }
      ];
    }

    const stats = await Topic.findAll({
      where: where, // 先筛选（不包括difficulty）
      attributes: [
        "difficulty",
        [Topic.sequelize!.fn("COUNT", Topic.sequelize!.col("id")), "count"],
      ],
      group: ["difficulty"], // 再分组统计
      raw: true,
    });

    return stats.map((stat) => ({
      difficulty: stat.difficulty as Difficulty,
      count: parseInt(stat.count as string),
    }));
  } catch (error) {
    throw new Error(`获取难度统计失败: ${error}`);
  }
};

/**
 * 获取审核状态统计
 */
export const getReviewStatusStats = async (
  params: TopicQueryParams = {}
): Promise<Array<{ reviewStatus: ReviewStatus; count: number }>> => {
  try {
    const { domain, difficulty, submitterId, search } = params;

    // 构建筛选条件，但不包括reviewStatus筛选
    // 因为我们要统计所有reviewStatus的数量
    const where: any = {};
    if (domain) where.domain = domain;
    if (difficulty) where.difficulty = difficulty;
    if (submitterId) where.submitterId = submitterId;
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        // { description: { [Op.like]: `%${search}%` } }
      ];
    }

    const stats = await Topic.findAll({
      where: where, // 先筛选（不包括reviewStatus）
      attributes: [
        "reviewStatus",
        [Topic.sequelize!.fn("COUNT", Topic.sequelize!.col("id")), "count"],
      ],
      group: ["reviewStatus"], // 再分组统计
      raw: true,
    });

    return stats.map((stat) => ({
      reviewStatus: stat.reviewStatus as ReviewStatus,
      count: parseInt(stat.count as string),
    }));
  } catch (error) {
    throw new Error(`获取审核状态统计失败: ${error}`);
  }
};

// 为了保持向后兼容，导出TopicService对象
export const TopicService = {
  createTopic,
  getTopicById,
  getTopics,
  updateTopic,
  deleteTopic,
  reviewTopic,
  incrementStarCount,
  decrementStarCount,
  getDomainStats,
  getDifficultyStats,
  getReviewStatusStats,
};

export default TopicService;
